# Copyright (c) 2009 Supreet Sethi. All rights reserved.
# Licensed Artistic License

from optparse import OptionParser
import util
from xml.etree import ElementTree as et

import logging
logger = logging.getLogger('sifysnake')
hdlr = logging.FileHandler('./snake.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)

class Const:
    login_key = "3654egf^@q|$ds!as87&#%35ef@|d!s7#"
    const_hex = "29355d121c211de0717c127166713ebb"
    server_address = "http://202.144.65.70"
    logout_url = server_address + ":8090/bbandclient_v30/logout.php"
    login_url = server_address + ":8090"
    client_version = "3.22"
    fcstring =  "?macaddress=%s&srcip=192.168.1.1&version=" + client_version + "&os=xp"
    sify_docket = {}
    verbose = False
    cDock = {}
    
class SifySnake:
    def __init__(self, username, password, privateIP = None, 
                 mac = None):
        self.uname = username
        self.passwd = password
        self.platform = util.Platform()
        if mac:
            self.mac = mac
        else:
            self.mac = self.platform.getMACAddress()
        if privateIP:
            self.ip = privateIP
        else:
            self.ip = self.platform.getSystemIP()
        self.platform = util.Platform()
        self.ip = privateIP
    
    def stage1Parse(self, text):
        l1parsedXML = et.fromstring(text)
        xml = l1parsedXML
        loginURL = xml.find(".//LoginURL").text
        sessionID = xml.find(".//sessionID").text
        pvtIP = xml.find(".//pvtIP").text
        serverTime =xml.find(".//ServerTime").text
        logoutURL =xml.find(".//Logout").attrib['url']
        samIP = xml.find(".//samIP").text
        activeUser = xml.find(".//IsActiveUser").text
        temp_dict  = {
            'loginURL': loginURL,
            'sessionID': sessionID,
            'pvtIP': pvtIP,
            'serverTime': serverTime,
            'logoutURL': logoutURL,
            'samIP': samIP,
            'activeUser': activeUser
            }
        return temp_dict
    
    def stage2Parse(self, text):
        l2parsedXML = et.fromstring(text)
        xml = l2parsedXML
        responseCode = xml.find(".//ResponseCode").text
        replyMessage = xml.find(".//ReplyMessage").text
        return responseCode, replyMessage


    def calculateBlowfishKeys(self, login_key, pvtIP, sessionID, 
                              serverTime):
        netString = self.platform.getNetAddress(self.ip)
        tstamp = self.platform.getTimeStamp(serverTime)
        srcKey = login_key + netString + sessionID
        txtKey = login_key + tstamp + netString + sessionID
        return self.platform.getMD5(srcKey), self.platform.getMD5(txtKey)
    

    def createStage2Query(self, encPasswd):
        connText = "%s|%s|%s|%s|%s|%s|%s"  %(self.uname,
                                             encPasswd,
                                             self.ip,
                                             self.mac,
                                             Const.client_version,
                                             Const.cDock['sessionID'],
                                             Const.const_hex)
        if Const.verbose == True:
            print connText
        return connText


    

    def login(self):
        iniURL = Const.fcstring % (self.mac)
        initXML = util.postToServer(Const.login_url + iniURL, None,
                                   Const)
        initial_dict = self.stage1Parse(initXML)
        Const.cDock.update(initial_dict)
        
        # Second Level of Login
        aKey, bKey = self.calculateBlowfishKeys(Const.login_key,
                                                Const.cDock['pvtIP'],
                                                Const.cDock['sessionID'],
                                                Const.cDock['serverTime'])
                                                  
  
        encPasswd = self.platform.getEncrypted(aKey, self.passwd)
        macAddress = self.mac
        connText = self.createStage2Query(encPasswd)
        content = self.platform.getEncrypted(bKey, connText)
        print content
        servXML = util.postToServer(Const.cDock['loginURL'], 
                                             content, Const)
        return self.stage2Parse(servXML)

    def logout(self):
        sysIP = self.platform.getSystemIP()
        authreq = {'username': self.uname,
                   'password': self.passwd,
                   'srcip': self.ip,
                   'macaddress':self.mac,
                   'sessionid': Const.cDock['sessionID'] }
        content = util.postToServer(Const.cDock['logoutURL'], 
                                             authreq, Const)
        return content

if __name__=='__main__':
    import sys
    import ConfigParser
    from optparse import OptionParser
    from os import access, R_OK
    parser = OptionParser()
    parser.add_option("-c", "--config", dest="filename", 
                      default="/etc/sifysnake.cfg")
    parser.add_option("-p", "--profile", dest="profile", default="Default")
    (options, args) = parser.parse_args()
    if access(options.filename,R_OK ) == False:
        print >> sys.stderr , "Cant access %s" % options.filename
        sys.exit(1)
    config = ConfigParser.RawConfigParser()
    config.read(options.filename)
    try:
        config.get(options.profile, 'Username')
    except ConfigParser.NoSectionError:
        print >> sys.stderr , "Cant access profile %s" % options.profile
        sys.exit(2)
    username = config.get(options.profile, 'Username')
    password = config.get(options.profile, 'Password')
    privateip = config.get(options.profile, 'PrivateIP')
    macaddress = config.get(options.profile, 'MacAddress')
    
    sify = SifySnake(username, password, privateip, macaddress)
    sify.login()
    from heartbeat import HeartBeat
    hb = HeartBeat(sify, 10)
    hb.start()
